import QtQuick
import QtQuick.Controls
import QtQuick3D
import QtQuick3D.Physics
import QtQuick3D.Helpers

import QtQuickRO

import "../EventBus"
import "../framework"

/*
*这是一个第三人称视角色架构
它由三个基本结构组成：底座（characterController），摄像基座（cameraBase），角色基座（bodyBase）
底座为一个CharacterController，用于控制角色位移。底座只能平移不能旋转（为了优化）
摄像基座用于控制摄像机视角
角色基座用于放置角色模型，角色基座只能旋转不能位移
目前摄像机朝向不会同步给客户端
*/

Character
{
    id:root

    //从关卡上下文中获取射线检测器
    property RayPicker picker:rayPicker

    property alias characterTurnSpeed:charaterDirectionController.turnSpeed

    property alias bodyBase:bodyBase
    property alias cameraBase:cameraBase
    property alias cameraPitchBase:pitchBase//控制摄像机俯仰
    property alias camera:cameraPerspective

    property alias cameraYaw:cameraBase.eulerRotation.y
    property alias cameraPitch:pitchBase.eulerRotation.x
    property alias cameraDistance:cameraPerspective.z//摄像机距离

    //控制角色朝向，这是个同步变量。需要从服务端设置
    property alias characterDirection:shared.characterDirection

    //适合的摄像机距离。实际距离受模型影响
    property alias prefferedCameraDistance:cameraPerspective.prefferedCameraDistance

    midAirControl: false//角色不会在空中进行移动

    Node{//角色基座，用于放置角色模型等可视化组件
        id:bodyBase
        parent: characterController
        position.y:- (capsuleShape.diameter / 2 + capsuleShape.height / 2)
    }

    //摄像机基座
    Node{
        id:cameraBase
        parent: characterController
        Node{
            id:pitchBase
            eulerRotation.x:23
            position.z:-1

            //控制俯仰的基座
            PerspectiveCamera {
                id: cameraPerspective

                property real prefferedCameraDistance:400
                FrameAnimation{
                    //通过射线检测实时获取摄像机与外界碰撞信息
                    running: true
                    function setDistance(targetDis){
                        let minMove = 100

                        if(Math.abs(cameraPerspective.position.z - targetDis) < minMove)
                        {
                            cameraPerspective.position.z = targetDis
                        }
                        else{
                            if(targetDis > cameraPerspective.position.z)
                            {
                                cameraPerspective.position.z += minMove
                            }
                            else{
                                cameraPerspective.position.z -= minMove
                            }
                        }
                    }

                    onTriggered: {
                        let origin = pitchBase.mapPositionToScene(Qt.vector3d(0,0,0))
                        let direction = pitchBase.mapDirectionToScene(Qt.vector3d(0,0,-1));
                        let ret = picker.rayPick(origin,direction)

                        let targetDis = 0
                        if(ret.objectHit)
                        {
                            targetDis = -Math.min(Math.max((ret.distance - 100),0),prefferedCameraDistance)
                        }else{
                            targetDis = -prefferedCameraDistance
                        }

                        setDistance(targetDis)
                    }

                }

                eulerRotation.y:180
            }
        }
    }

    ROSharedObject{
        id:shared
        //同步角色朝向
        property real characterDirection:0
    }

    //角色面朝方向的控制器
    FrameAnimation{
        id:charaterDirectionController
        property real turnSpeed:1000.0
        running: true

        onTriggered: {
            let target = shared.characterDirection
            let cur = bodyBase.eulerRotation.y
            if(target === cur)
            {
                return
            }

            let delta = turnSpeed * frameTime

            if(Math.abs(target - cur) < delta)
            {
                bodyBase.eulerRotation.y = target
                return
            }

            let factor = 1

            if(target > cur)
            {
                if(target - cur < 180)
                {
                    factor = 1
                }
                else{
                    factor = -1
                }
            }
            else{
                if(cur - target < 180)
                {
                    factor = -1
                }
                else{
                    factor = 1
                }
            }

            let ret = cur + delta * factor

            if(ret > 180)
            {
                ret -= 360
            }
            else if(ret <-180)
            {
                ret += 360
            }

            bodyBase.eulerRotation.y = ret
        }
    }

    Node {
        id: __materialLibrary__
    }
}
